﻿namespace AddressBook.Business.Contact
{
	#region "Using Statements"
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;

	using Csla;
	using Csla.Data;
	using Csla.Validation;

	using Business.Event;
	#endregion

	[Serializable]
	public class Event : BusinessBase<Event>
	{
		#region "Business Methods"

		#region "Private Static Member Variables"

		private static PropertyInfo<Int32> IdProperty = RegisterProperty<Int32>(e => e.Id);
		private static PropertyInfo<String> NameProperty = RegisterProperty<String>(e => e.Name);
		private static PropertyInfo<Int32> LocationIdProperty = RegisterProperty<Int32>(e => e.LocationId);
		private static PropertyInfo<SmartDate> ModifiedDateProperty = RegisterProperty<SmartDate>(e => e.ModifiedDate);
		private static PropertyInfo<EventGuestList> GuestsProperty = RegisterProperty<EventGuestList>(e => e.Guests);

		#endregion

		#region "Public Properties"

		public Int32 Id
		{
			get { return GetProperty(IdProperty); }

			internal set { LoadProperty(IdProperty, value); }
		}

		public String Name
		{
			get { return GetProperty(NameProperty); }

			set { SetProperty(NameProperty, value); }
		}

		public Int32 LocationId
		{
			get { return GetProperty(LocationIdProperty); }

			set { SetProperty(LocationIdProperty, value); }
		}

		public String ModifiedDate
		{
			get { return GetProperty(ModifiedDateProperty).ToString(); }
		}

		public EventGuestList Guests
		{
			get
			{
				if (!(FieldManager.FieldExists(GuestsProperty)))
				{
					LoadProperty(GuestsProperty, EventGuestList.NewEventGuestList());
				}

				return GetProperty(GuestsProperty);
			}
		}

		#endregion

		#endregion

		#region "Factory Methods"

		public static Event NewEvent()
    {
      return DataPortal.Create<Event>();
    }

		public static Event GetEvent(Int32 id)
    {
      return DataPortal.Fetch<Event>(new SingleCriteria<Event, Int32>(id));
    }

		public static void DeleteEvent(Int32 id)
    {
      DataPortal.Delete(new SingleCriteria<Event, Int32>(id));
    }

		private Event()
    { /* require use of factory methods */ }

		#endregion

		#region "Data Access"

		[RunLocal()]
		protected override void DataPortal_Create()
		{
			using (BypassPropertyChecks)
			{
				ValidationRules.CheckRules();
			}
		}

		private void DataPortal_Fetch(SingleCriteria<Event, Int32> criteria)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// get event data
				AddressBook.Business.Model.Event eventData = ctx.DataContext.Events.First(e => e.Id == criteria.Value);

				using (BypassPropertyChecks)
				{
					this.Id = eventData.Id;
					this.Name = eventData.Name;
					this.LocationId = eventData.LocationId;

					LoadProperty(ModifiedDateProperty, eventData.ModifiedDate);

          //Load Child object
          LoadProperty(GuestsProperty, EventGuestList.GetEventGuestList(eventData.Guests.ToArray()));
				}
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_Insert()
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// insert event data
				using (BypassPropertyChecks)
				{
					AddressBook.Business.Model.Event eventData = new AddressBook.Business.Model.Event();

					eventData.Name = this.Name;
					eventData.LocationId = this.LocationId;
					eventData.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.Events.InsertOnSubmit(eventData);
					ctx.DataContext.SubmitChanges();

					this.Id = eventData.Id;
				}

        FieldManager.UpdateChildren(this);
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_Update()
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				AddressBook.Business.Model.Event eventData = ctx.DataContext.Events.First(e => e.Id == this.Id);

				// update event data
				using (BypassPropertyChecks)
				{
					eventData.Name = this.Name;
					eventData.LocationId = this.LocationId;
					eventData.ModifiedDate = System.DateTime.Now;

					ctx.DataContext.SubmitChanges();
				}

        FieldManager.UpdateChildren(this);
			}
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		protected override void DataPortal_DeleteSelf()
		{
			DataPortal_Delete(new SingleCriteria<Event, Int32>(this.Id));
		}

		[Transactional(TransactionalTypes.TransactionScope)]
		private void DataPortal_Delete(SingleCriteria<Event, Int32> criteria)
		{
			using (var ctx = ContextManager<AddressBook.Business.Model.AddressBookDataContext>.GetManager(AddressBook.Business.Model.Database.AddressBook))
			{
				// get event data
				AddressBook.Business.Model.Event eventData = ctx.DataContext.Events.First(e => e.Id == criteria.Value);

        // delete the guests assigned to this event.
				foreach (AddressBook.Business.Model.Guest guest in ctx.DataContext.Guests.Where(g => g.EventId == eventData.Id))
        {
          ctx.DataContext.Guests.DeleteOnSubmit(guest);
        }

        ctx.DataContext.SubmitChanges();

				// delete event data
				ctx.DataContext.Events.DeleteOnSubmit(eventData);
				ctx.DataContext.SubmitChanges();

        LoadProperty(GuestsProperty, EventGuestList.NewEventGuestList());
			}
		}

		#endregion
	}
}